package com.jiangchao.annotationmvc.core.listener;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.jiangchao.annotationmvc.core.annotation.Controller;
import com.jiangchao.annotationmvc.core.annotation.Mapping;
import com.jiangchao.annotationmvc.core.util.PackageUtils;

public class AnnotationListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("系统已经注销");

	}

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("自定义注解监听器正在加载...");
//		1. 获取需要扫描的包路径
		String packageScanpath = sce.getServletContext().getInitParameter("package-scan-path");
//		2. 解析所有需要扫描的包路径
		String[] packageScanpaths = packageScanpath.split(",");
//		3. 获得所有的类
		Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
		for (String string : packageScanpaths) {
			classes.addAll(PackageUtils.getClasses(packageScanpath));
		}
//		4. 遍历解析classes，获得映射关系
		Map<String,Map<String,String>> pathMapping = new HashMap<String,Map<String,String>>();
		for (Class<?> clazz : classes) {
			if (clazz.isAnnotationPresent(Controller.class)) {
				this.controllerHanler(pathMapping,clazz);
			}
		}
		sce.getServletContext().setAttribute("pathMapping", pathMapping);

		System.out.println("自定义注解监听器加载完成...");

	}
	
	private void controllerHanler(Map<String,Map<String,String>> map,Class clazz){
		String parentPath = "";
		String realPath = "";
//		1. 如果类上游@Mapping注解，则视为父路径
		if (clazz.isAnnotationPresent(Mapping.class)) {
			Mapping mapping = (Mapping) clazz.getAnnotation(Mapping.class);
			parentPath = mapping.value();
		}
//		2.获得该类的所有方法
		Method[] methods = clazz.getDeclaredMethods();
//		3. 遍历所有的方法
		for (Method method : methods) {
//			只对方法上有@Mapping注解的方法进行处理
			if (method.isAnnotationPresent(Mapping.class)) {
				Mapping mapping = (Mapping) method.getAnnotation(Mapping.class);
				realPath = parentPath +mapping.value();
			}
			Map<String,String> classMethodMap = new HashMap<String,String>();
			classMethodMap.put(clazz.getName(), method.getName());
			map.put(realPath, classMethodMap);
			
		}
	}

}
